<script>

	// es6方法indexOf,lastindexOf,reduce,flat,foreach，map，every，some实现================================
	var arrEs6Fn = {
		indexOf() {
			if (!Array.indexOf) {
				Array.prototype.indexOf = function (obj) {
					for (var i = 0; i < this.length; i++) {
						if (this[i] == obj) {
							return i;
						}
					}
					return -1;
				}
			}
		},
		lastIndexOf() {
			if (!Array.prototype.lastIndexOf) {
				Array.prototype.lastIndexOf = function (searchElement /*, fromIndex*/) {
					'use strict';

					if (this === void 0 || this === null) {
						throw new TypeError();
					}

					var n, k,
						t = Object(this),
						len = t.length >>> 0;
					if (len === 0) {
						return -1;
					}

					n = len - 1;
					if (arguments.length > 1) {
						n = Number(arguments[1]);
						if (n != n) {
							n = 0;
						}
						else if (n != 0 && n != (1 / 0) && n != -(1 / 0)) {
							n = (n > 0 || -1) * Math.floor(Math.abs(n));
						}
					}

					for (k = n >= 0
						? Math.min(n, len - 1)
						: len - Math.abs(n); k >= 0; k--) {
						if (k in t && t[k] === searchElement) {
							return k;
						}
					}
					return -1;
				};
			}
		},
		reduce() {
			Array.prototype.reduce = function (fn, init) {
				var arr = this   // this就是调用reduce方法的数组
				var total = init || arr[0]   // 有初始值使用初始值
				// 有初始值的话从0遍历， 否则从1遍历
				for (var i = init ? 0 : 1; i < arr.length; i++) {
					total = fn(total, arr[i], i, arr)
				}
				return total
			}
		},
		flat() {
			Array.prototype.flat = function (dep = 1) {

				return this.reduce((acc, val) => {

					return acc.concat(Array.isArray(val) && dep > 0 ?
						// 这里的三目就是防止这个现象：[3].concat([4]) // 结果为[3, 4]
						val.flat(--dep) : Array.isArray(val) ? [val] : val);

				}, [])
			}
		},
		some() {
			if (!Array.prototype.some) {
				Array.prototype.some = function (fun /*, thisArg */) {
					'use strict';
					if (this === void 0 || this === null)
						throw new TypeError();

					var t = Object(this);
					var len = t.length >>> 0;
					if (typeof fun !== 'function')
						throw new TypeError();

					var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
					for (var i = 0; i < len; i++) {
						if (i in t && fun.call(thisArg, t[i], i, t))
							return true;
					}

					return false;
				};
			}
		},
		every() {
			if (!Array.prototype.every) {
				Array.prototype.every = function (fun /*, thisArg */) {
					'use strict';

					if (this === void 0 || this === null)
						throw new TypeError();

					var t = Object(this);
					var len = t.length >>> 0;
					if (typeof fun !== 'function')
						throw new TypeError();

					var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
					for (var i = 0; i < len; i++) {
						if (i in t && !fun.call(thisArg, t[i], i, t))
							return false;
					}

					return true;
				};
			}
		},
		filter() {
			if (!Array.prototype.filter) {
				Array.prototype.filter = function (fun /*, thisArg */) {
					"use strict";
					if (this === void 0 || this === null)
						throw new TypeError();
					var t = Object(this);
					var len = t.length >>> 0;
					if (typeof fun !== "function")
						throw new TypeError();
					var res = [];
					var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
					for (var i = 0; i < len; i++) {
						if (i in t) {
							var val = t[i];
							if (fun.call(thisArg, val, i, t))
								res.push(val);
						}
					}
					return res;
				};
			}
		},
		map() {
			if (!Array.prototype.map) {

				Array.prototype.map = function (callback, thisArg) {

					var T, A, k;

					if (this == null) {
						throw new TypeError(' this is null or not defined');
					}

					// 1. Let O be the result of calling ToObject passing the |this| 
					//    value as the argument.
					var O = Object(this);

					// 2. Let lenValue be the result of calling the Get internal 
					//    method of O with the argument "length".
					// 3. Let len be ToUint32(lenValue).
					var len = O.length >>> 0;

					// 4. If IsCallable(callback) is false, throw a TypeError exception.
					// See: http://es5.github.com/#x9.11
					if (typeof callback !== 'function') {
						throw new TypeError(callback + ' is not a function');
					}

					// 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
					if (arguments.length > 1) {
						T = thisArg;
					}

					// 6. Let A be a new array created as if by the expression new Array(len) 
					//    where Array is the standard built-in constructor with that name and 
					//    len is the value of len.
					A = new Array(len);

					// 7. Let k be 0
					k = 0;

					// 8. Repeat, while k < len
					while (k < len) {

						var kValue, mappedValue;

						// a. Let Pk be ToString(k).
						//   This is implicit for LHS operands of the in operator
						// b. Let kPresent be the result of calling the HasProperty internal 
						//    method of O with argument Pk.
						//   This step can be combined with c
						// c. If kPresent is true, then
						if (k in O) {

							// i. Let kValue be the result of calling the Get internal 
							//    method of O with argument Pk.
							kValue = O[k];

							// ii. Let mappedValue be the result of calling the Call internal 
							//     method of callback with T as the this value and argument 
							//     list containing kValue, k, and O.
							mappedValue = callback.call(T, kValue, k, O);

							// iii. Call the DefineOwnProperty internal method of A with arguments
							// Pk, Property Descriptor
							// { Value: mappedValue,
							//   Writable: true,
							//   Enumerable: true,
							//   Configurable: true },
							// and false.

							// In browsers that support Object.defineProperty, use the following:
							// Object.defineProperty(A, k, {
							//   value: mappedValue,
							//   writable: true,
							//   enumerable: true,
							//   configurable: true
							// });

							// For best browser support, use the following:
							A[k] = mappedValue;
						}
						// d. Increase k by 1.
						k++;
					}

					// 9. return A
					return A;
				};
			}
		},
		forEach() {
			if (!Array.prototype.forEach) {
				Array.prototype.forEach = function (fun /*, thisp*/) {
					var len = this.length;
					if (typeof fun != "function")
						throw new TypeError();
					var thisp = arguments[1];
					for (var i = 0; i < len; i++) {
						if (i in this)
							fun.call(thisp, this[i], i, this);
					}
				};
			}
		},
		find() {
			Array.prototype.find = function (fn) { // 该方法返回第一个判断为true的值
				if (typeof fn != 'function') {
					throw TypeError('err function')
				}
				for (var i = 0; i < this.length; i++) {
					if (fn(this[i])) {
						return this[i]
					}
				}
				return undefined // 没有匹配则返回undefined
			}
		}
	}
</script>